#include "AiMonitor.h"
#include "opencv2/opencv.hpp"
#include "../log/SysLog.h"
#include "../AiBox.h"
#include "../service/DeviceService.h"
#include "../util/FileUtil.h"

AiMonitor::AiMonitor()
	: m_run(true)
{
}

AiMonitor::~AiMonitor()
{
#if WIN32
	cv::destroyAllWindows();
#endif
}

void AiMonitor::Start()
{
	m_run = true;
	m_thread = std::thread([&]() {
		int pageIndex = 0, pageSize = 10;

		// 数据库设备表
		std::vector<DeviceInfo> db_devices;

		// 分页检测设备
		DeviceService deviceService;
		while (m_run)
		{
			// 获取检测器
			Detectors detectors;
			{
				std::unique_lock<std::mutex> _guard(m_lock);
				detectors = m_detectors;
			}

			// 查询当前页设备
			std::vector<DeviceInfo> devices;
			deviceService.FindPage(pageIndex, pageSize, devices);
			LOG_INFO("current detect task count: {}", detectors.size());

			// 查询完成继续查
			if (devices.size() <= 0)
			{
				// 关闭已删除设备
				for (Detectors::iterator it = detectors.begin(); it != detectors.end();)
				{
					// 当前检测器
					DetectorPtr detector = it->second;
					// 数据库是否存在
					bool find = false;
					DeviceInfo info;
					for (size_t index = 0; index < db_devices.size(); ++index)
					{
						if (it->first == db_devices[index].GetId())
						{
							find = true;
							info = db_devices[index];
							break;
						}
					}
					// 数据库已删除
					if (!find)
					{
						detector->Stop();
						{
							std::unique_lock<std::mutex> _guard(m_lock);
							m_detectors.erase(it->first);
						}
						it = detectors.erase(it);
					}
					// 设备已更新
					else if (detector->Change(info))
					{
						detector->Stop();
						{
							std::unique_lock<std::mutex> _guard(m_lock);
							m_detectors.erase(it->first);
						}
						it = detectors.erase(it);
					}
					else
					{
						it++;
					}
				}
				// 清除列表重查
				db_devices.clear();
				// 从第一页继续查
				pageIndex = 0;
				// 睡眠n秒-快速退出
				bool exit = false;
				for (int index = 0; index < 5; ++index)
				{
					if (!m_run)
					{
						exit = true;
						break;
					}
					std::this_thread::sleep_for(std::chrono::seconds(1));
				}
				// 分段睡眠退出
				if (exit)
				{
					break;
				}
				continue;
			}

			// 添加到数据存储表
			db_devices.insert(db_devices.end(), devices.begin(), devices.end());

			// 检测所有设备启用状态
			for (int index = 0; index < devices.size(); ++index)
			{
				// 设备启用检测
				if (devices[index].GetEnabled())
				{
					// 启动检测
					bool not_expired = DateTime::BetweenTimeNow(devices[index].GetStartTime(), devices[index].GetEndTime());
					if (not_expired && detectors.find(devices[index].GetId()) == detectors.end())
					{
						DetectorPtr detector = std::make_shared<Detector>(devices[index]);
						if (detector)
						{
							detector->Start();
						}
						detectors[devices[index].GetId()] = detector;
						{
							std::unique_lock<std::mutex> _guard(m_lock);
							m_detectors[devices[index].GetId()] = detector;
						}
					}
					// 已经过期
					else if (!not_expired && detectors.find(devices[index].GetId()) != detectors.end())
					{
						// 移除检测
						DetectorPtr detector = detectors[devices[index].GetId()];
						if (detector)
						{
							detector->Stop();
						}
						detectors.erase(devices[index].GetId());
						{
							std::unique_lock<std::mutex> _guard(m_lock);
							m_detectors.erase(devices[index].GetId());
						}
					}
				}
				// 设备禁用检测
				else if (detectors.find(devices[index].GetId()) != detectors.end())
				{
					// 移除检测
					DetectorPtr detector = detectors[devices[index].GetId()];
					if (detector)
					{
						detector->Stop();
					}
					detectors.erase(devices[index].GetId());
					{
						std::unique_lock<std::mutex> _guard(m_lock);
						m_detectors.erase(devices[index].GetId());
					}
				}
			}

			// 查询也一页
			pageIndex = pageIndex + pageSize;
			// 快速退出
			for (int index = 0; index < 15; ++index)
			{
				if (!m_run)
				{
					break;
				}
				std::this_thread::sleep_for(std::chrono::seconds(1));
			}
		}

		// 关闭检测器
		std::unique_lock<std::mutex> _guard(m_lock);
		for (Detectors::iterator it = m_detectors.begin(); it != m_detectors.end(); ++it)
		{
			DetectorPtr detector = it->second;
			if (detector)
			{
				detector->Stop();
			}
		}
		m_detectors.clear();
	});
}

void AiMonitor::Stop()
{
	m_run = false;
	if (m_thread.joinable())
	{
		m_thread.join();
	}
}

DetectorPtr AiMonitor::Find(std::string device)
{
	DetectorPtr detector;
	{
		std::unique_lock<std::mutex> _guard(m_lock);
		if (m_detectors.find(device) != m_detectors.end())
		{
			detector = m_detectors[device];
		}
	}
	return detector;
}